package com.blogspot.mkorwel.jaas;

import java.util.HashMap;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

/**
 * 
 * @author mkorwel
 * 
 */
public class MyLoginModule implements LoginModule {

	private Map<String, String> usernameAndPassword = new HashMap<String, String>() {

		private static final long serialVersionUID = -2695491152140640122L;

		{
			put("user1", "user");
			put("admin", "admin");
		}
	};
	private Map<String, String> usernameAndRoles = new HashMap<String, String>() {

		private static final long serialVersionUID = 1136203053244663646L;

		{
			put("user1", "user");
			put("admin", "admin");
		}
	};

	// initial state
	private Subject subject;
	private CallbackHandler callbackHandler;
	@SuppressWarnings("unused")
	private Map<String, ?> sharedState;
	@SuppressWarnings("unused")
	private Map<String, ?> options;

	// username and password
	private String username;
	private String password;

	private MyPrincipal userPrincipal;

	@Override
	public void initialize(Subject subject, CallbackHandler callbackHandler,
			Map<String, ?> sharedState, Map<String, ?> options) {

		this.subject = subject;
		this.callbackHandler = callbackHandler;
		this.sharedState = sharedState;
		this.options = options;

	}

	@Override
	public boolean login() throws LoginException {

		Callback[] callbacks = new Callback[2];
		callbacks[0] = new NameCallback("user name: ");
		callbacks[1] = new PasswordCallback("password: ", false);

		try {
			// pobranie loginu
			callbackHandler.handle(callbacks);
			username = ((NameCallback) callbacks[0]).getName();

			// pobranie hasla
			char[] tmpPassword = ((PasswordCallback) callbacks[1])
					.getPassword();
			if (tmpPassword == null) {
				tmpPassword = new char[0];
			}
			password = new String(tmpPassword);

			((PasswordCallback) callbacks[1]).clearPassword();

		} catch (java.io.IOException ioe) {
			throw new LoginException(ioe.toString());
		} catch (UnsupportedCallbackException uce) {
			throw new LoginException("Error: " + uce.getCallback().toString()
					+ " not available to garner authentication information "
					+ "from the user");
		}

		// weryfikacje loginu i hasla
		return (usernameAndPassword.containsKey(username) && password
				.equals(usernameAndPassword.get(username)));
	}

	@Override
	public boolean commit() throws LoginException {

		userPrincipal = new MyPrincipal(username);

		if (!subject.getPrincipals().contains(userPrincipal)) {
			subject.getPrincipals().add(userPrincipal);
			MyGroup role = new MyGroup("Roles");
			role.addMember(new MyPrincipal(usernameAndRoles.get(username)));
			subject.getPrincipals().add(role);
		}

		return true;
	}

	@Override
	public boolean abort() throws LoginException {

		username = null;
		password = null;
		userPrincipal = null;

		return true;
	}

	@Override
	public boolean logout() throws LoginException {

		subject.getPrincipals().remove(userPrincipal);

		username = null;
		password = null;
		userPrincipal = null;

		return true;
	}
}